package model

import (
	"context"
	"fmt"

	"github.com/Masterminds/squirrel"
	"github.com/zeromicro/go-zero/core/stores/sqlc"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

var _ SysMenuModel = (*customSysMenuModel)(nil)

type (
	// SysMenuModel is an interface to be customized, add more methods here,
	// and implement the added methods in customSysMenuModel.
	SysMenuModel interface {
		sysMenuModel
		withSession(session sqlx.Session) SysMenuModel
		FindMenuIdsByRoleId(ctx context.Context, roleId int64) ([]int64, error)
		FindMenuListByRoleId(ctx context.Context, roleId int64) ([]*SysMenu, error)
		FindMenuListByIds(ctx context.Context, menuIds []int64) ([]*SysMenu, error)
		List(ctx context.Context) ([]*SysMenu, error)
		ChildCount(ctx context.Context, parentId int64) (uint64, error)
	}

	customSysMenuModel struct {
		*defaultSysMenuModel
	}
)

// NewSysMenuModel returns a model for the database table.
func NewSysMenuModel(conn sqlx.SqlConn) SysMenuModel {
	return &customSysMenuModel{
		defaultSysMenuModel: newSysMenuModel(conn),
	}
}

func (m *customSysMenuModel) withSession(session sqlx.Session) SysMenuModel {
	return NewSysMenuModel(sqlx.NewSqlConnFromSession(session))
}

func (m *customSysMenuModel) FindMenuIdsByRoleId(ctx context.Context, roleId int64) ([]int64, error) {
	query := fmt.Sprintf("select `menu_id` from %s where `role_id` = ?", m.table)

	var resp []int64
	if err := m.conn.QueryRowsCtx(ctx, &resp, query, roleId); err != nil {
		return nil, err
	}

	return resp, nil

}

func (m *customSysMenuModel) FindMenuListByRoleId(ctx context.Context, roleId int64) ([]*SysMenu, error) {
	query := fmt.Sprintf("select %s from %s where `role_id` = ?", sysMenuRows, m.table)

	var resp []*SysMenu
	if err := m.conn.QueryRowsCtx(ctx, &resp, query, roleId); err != nil {
		return nil, err
	}

	return resp, nil

}

func (m *customSysMenuModel) FindMenuListByIds(ctx context.Context, menuIds []int64) ([]*SysMenu, error) {

	sqlBilder := squirrel.Select(sysMenuRows).From(m.table).Where(squirrel.Eq{"menu_id": menuIds})

	query, args, err := sqlBilder.ToSql()
	if err != nil {
		return nil, err
	}
	var resp []*SysMenu

	err = m.conn.QueryRowsCtx(ctx, &resp, query, args...)
	switch err {
	case nil:
		return resp, nil
	case sqlc.ErrNotFound:
		return nil, ErrNotFound
	default:
		return nil, err
	}
}

func (m *customSysMenuModel) List(ctx context.Context) ([]*SysMenu, error) {

	sqlBuilder := squirrel.Select(sysMenuRows).From(m.table)

	query, args, err := sqlBuilder.ToSql()
	if err != nil {
		return nil, err
	}
	var resp []*SysMenu

	err = m.conn.QueryRowsCtx(ctx, &resp, query, args...)
	switch err {
	case nil:
		return resp, nil
	case sqlc.ErrNotFound:
		return nil, ErrNotFound
	default:
		return nil, err
	}
}

func (m *customSysMenuModel) ChildCount(ctx context.Context, parentId int64) (uint64, error) {
	sqlBuilder := squirrel.Select("count(menu_id)").From(m.table).Where("parent_id = ?", parentId)
	query, args, err := sqlBuilder.ToSql()
	if err != nil {
		return 0, err
	}

	var resp uint64
	if err := m.conn.QueryRowCtx(ctx, &resp, query, args...); err != nil {
		return 0, err
	}

	return resp, nil
}
